﻿using System;
using System.Net;
using System.Threading.Tasks;
using System.Text;
using System.IO;


namespace TestApp.WebService
{
    public sealed class WSManager
    {
        private static volatile WSManager instance;
        private static object syncRoot = new Object();

        // Private constructor
        private WSManager() {}


        // Singleton Instance
        public static WSManager Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                            instance = new WSManager();
                    }
                }

                return instance;
            }
        }

        // Executes a request
        public async Task<WSResponse> ExecuteRequest(String HTTPMethod, String URI, String body, String authorization, String contentType, String accept)
        {
            HttpWebRequest httpWebRequest = CreateRequest(HTTPMethod, URI, authorization, contentType, accept);

            // Check for body
            if (body != null)
            {
                // Request Content
                Stream outputStream = await httpWebRequest.GetRequestStreamAsync().ConfigureAwait(false); 

                // Convert the string into a byte array. 
                byte[] byteArray = Encoding.UTF8.GetBytes(body);

                // Write to the request stream.
                await outputStream.WriteAsync(byteArray, 0, body.Length).ConfigureAwait(false);
                outputStream.Close();
            }

            // Try to get response. Catch Web Service or Connection Error
            HttpWebResponse response;
            try
            {
                response = (HttpWebResponse) await httpWebRequest.GetResponseAsync().ConfigureAwait(false);
            }
            catch (WebException ex)
            {
                response = ex.Response as HttpWebResponse;
            }

            return ParseWebResponse(response);
        }

        // Creates a WSResponse object containing the StatusCode and the Data received
        private WSResponse ParseWebResponse(HttpWebResponse response)
        {

           // Read Response
            Stream streamResponse = response.GetResponseStream();
            StreamReader streamRead = new StreamReader(streamResponse);
            string responseString = streamRead.ReadToEnd();

            // Close the stream object
            streamResponse.Close();
            streamRead.Close();

            // Release the HttpWebResponse
            response.Close();

            // Return WSResponse
            return new WSResponse(response.StatusCode, responseString);
        }


        // Creates a HttpWebRequest object with the passed HTTPMethod, URI, Authorization, ContentType, Accept Headers
        private HttpWebRequest CreateRequest(String HTTPMethod, String URI, String authorization, String contentType, String accept)
        {
            HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(URI);
            httpWebRequest.Accept = accept;
            httpWebRequest.ContentType = contentType;
            httpWebRequest.Method = HTTPMethod;
            httpWebRequest.Headers["Authorization"] = authorization;

            return httpWebRequest;
        }

    }
}
